package acm.蓝桥22;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class H_迷宫问题 {
	static int maxn = 2010;
	static int[][] q = new int[maxn * maxn][3];
	static int[][] dis = new int[maxn][maxn];
	static Map<String, List<int[]>> map = new HashMap<>();
	static int[][] dirs = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 }, };
	static int n, m;

	public static void main(String[] args) {
		Reader2 sc = new Reader2(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		for (int i = 0; i < m; i++) {
			int x1 = sc.nextInt();
			int y1 = sc.nextInt();
			int x2 = sc.nextInt();
			int y2 = sc.nextInt();
			String s1 = x1 + "," + y1;
			String s2 = x2 + "," + y2;
			List list1 = map.get(s1);
			if (list1 == null) {
				list1 = new ArrayList<>();
				map.put(s1, list1);
			}
			list1.add(new int[] { x2, y2 });
			List list2 = map.get(s2);
			if (list2 == null) {
				list2 = new ArrayList<>();
				map.put(s2, list2);
			}
			list2.add(new int[] { x1, y1 });
		}
		bfs();
		long sum=0;
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=n;j++) {
				sum+=dis[i][j];
			}
		}
		System.out.printf("%.2f",1.0*sum/(n*n));
	}

	public static void bfs() {
		for (int[] d : dis) {
			Arrays.fill(d, Integer.MAX_VALUE);
		}
		dis[n][n] = 0;
		int h = 0, t = 0;
		q[t][0] = n;
		q[t][1] = n;
		q[t][2] = 0;
		t++;
		while (h != t) {
			int[] cur = q[h++];
			h %= q.length;
			for (int[] dir : dirs) {
				int nx = cur[0] + dir[0];
				int ny = cur[1] + dir[1];
				if (nx >= 1 && nx <= n && 1 <= ny && ny <= n && (cur[2] + 1) < dis[nx][ny]) {
					dis[nx][ny] = cur[2] + 1;
					q[t][0] = nx;
					q[t][1] = ny;
					q[t][2] = dis[nx][ny];
					t=(t+1)%q.length;
				}
			}
			List<int[]> list = map.get(cur[0] + "," + cur[1]);
			if (list != null) {
				for (int[] next : list) {
					if ((cur[2] + 1) < dis[next[0]][next[1]]) {
						dis[next[0]][next[1]] = cur[2] + 1;
						q[t][0]=next[0];
						q[t][1]=next[1];
						q[t][2]=cur[2] + 1;
						t=(t+1)%q.length;
					}
				}
			}
		}
	}
	static class Reader2 {
        static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        static PrintWriter pw=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

        public Reader2(Object... o) {
        }

        public int nextInt() {
            try {
                in.nextToken();
            } catch (Exception ignored) {}
            return (int) in.nval;
        }
}

}
